#include "serialportmanager.h"
#include "../utils/logger.h"
#include <QDebug>

SerialPortManager::SerialPortManager(QObject *parent)
    : QObject(parent)
{
    Logger::instance()->log(LogLevel::Info, "SerialPortManager: 串口管理器初始化");
}

SerialPortManager::~SerialPortManager()
{
    // 负责所有串口的生命周期管理
    // 其他组件（如 PollScheduler）只借用串口指针，不管理生命周期
    closeAllPorts();
    Logger::instance()->log(LogLevel::Info, "SerialPortManager: 串口管理器销毁");
}

// 扫描可用串口
QStringList SerialPortManager::scanAvailablePorts()
{
    QStringList portList;
    const auto ports = QSerialPortInfo::availablePorts();

    for (const QSerialPortInfo &info : ports)
    {
        portList.append(info.portName());
        Logger::instance()->log(LogLevel::Debug,
                                QString("SerialPortManager: 发现串口: %1 (%2)").arg(info.portName(), info.description()));
    }

    return portList;
}

// 打开串口
bool SerialPortManager::openPort(const QString &portName, qint32 baudRate)
{
    // 检查串口是否已经打开
    if (m_ports.contains(portName))
    {
        Logger::instance()->log(LogLevel::Warning,
                                QString("SerialPortManager: 串口 %1 已经打开").arg(portName));
        return true;
    }

    // 创建串口对象（不设置父对象，手动管理生命周期）
    QSerialPort *port = new QSerialPort(portName);

    // 尝试打开串口
    if (!port->open(QIODevice::ReadWrite))
    {
        QString errorMsg = QString("SerialPortManager: 无法打开串口 %1: %2").arg(portName, port->errorString());
        Logger::instance()->log(LogLevel::Error, errorMsg);
        emit portError(portName, port->errorString());
        delete port;
        return false;
    }

    // 配置串口参数
    if (!configurePort(port, baudRate))
    {
        QString errorMsg = QString("SerialPortManager: 配置串口 %1 失败").arg(portName);
        Logger::instance()->log(LogLevel::Error, errorMsg);
        emit portError(portName, "配置失败");
        port->close();
        delete port;
        return false;
    }

    // 连接错误信号（使用队列连接，因为串口可能在其他线程中使用）
    connect(port, &QSerialPort::errorOccurred, this, &SerialPortManager::handleSerialError, Qt::QueuedConnection);

    // 保存到映射表
    m_ports.insert(portName, port);

    Logger::instance()->log(LogLevel::Info,
                            QString("SerialPortManager: 成功打开串口 %1, 波特率: %2").arg(portName).arg(baudRate));

    emit portOpened(portName);
    emit openedPortCountChanged();
    return true;
}

// 关闭串口
void SerialPortManager::closePort(const QString &portName)
{
    if (!m_ports.contains(portName))
    {
        return;
    }

    QSerialPort *port = m_ports.take(portName);
    if (port)
    {
        if (port->isOpen())
        {
            port->close();
        }
        port->deleteLater();

        Logger::instance()->log(LogLevel::Info,
                                QString("SerialPortManager: 关闭串口 %1").arg(portName));

        emit portClosed(portName);
        emit openedPortCountChanged();
    }
}

// 关闭所有串口
void SerialPortManager::closeAllPorts()
{
    QStringList portNames = m_ports.keys();
    for (const QString &portName : portNames)
    {
        closePort(portName);
    }
}

// 获取串口
QSerialPort *SerialPortManager::getPort(const QString &portName)
{
    // 返回串口指针供其他组件借用
    // 注意：调用者不应该删除返回的指针，生命周期由 SerialPortManager 管理
    return m_ports.value(portName, nullptr);
}

// 判断串口是否打开
bool SerialPortManager::isPortOpen(const QString &portName) const
{
    if (!m_ports.contains(portName))
    {
        return false;
    }
    return m_ports[portName]->isOpen();
}

// 获取已打开的串口
QStringList SerialPortManager::getOpenedPorts() const
{
    return m_ports.keys();
}

// 处理串口错误
void SerialPortManager::handleSerialError(QSerialPort::SerialPortError error)
{
    if (error == QSerialPort::NoError)
    {
        return;
    }

    // 忽略 TimeoutError 和 ResourceError（这些错误在正常的 Modbus 通信中很常见）
    if (error == QSerialPort::TimeoutError || error == QSerialPort::ResourceError)
    {
        return;
    }

    QSerialPort *port = qobject_cast<QSerialPort *>(sender());
    if (!port)
    {
        return;
    }

    QString portName = port->portName();
    QString errorMsg = port->errorString();

    // 只记录严重错误（减少日志输出）
    Logger::instance()->log(LogLevel::Warning,
                            QString("SerialPortManager: 串口 %1 错误: %2").arg(portName, errorMsg));

    emit portError(portName, errorMsg);
}

// 配置串口
bool SerialPortManager::configurePort(QSerialPort *port, qint32 baudRate)
{
    if (!port)
    {
        return false;
    }

    // 设置波特率
    if (!port->setBaudRate(baudRate))
    {
        return false;
    }

    // 设置数据位：8位
    if (!port->setDataBits(QSerialPort::Data8))
    {
        return false;
    }

    // 设置校验位：无校验
    if (!port->setParity(QSerialPort::NoParity))
    {
        return false;
    }

    // 设置停止位：1位
    if (!port->setStopBits(QSerialPort::OneStop))
    {
        return false;
    }

    // 设置流控：无流控
    if (!port->setFlowControl(QSerialPort::NoFlowControl))
    {
        return false;
    }

    return true;
}
